%{
#include "exp_parser.h"
#include "exp_lexer.h" 
#include "data_memory.h"

void yyerror(int *ret, yyscan_t scanner, const char *msg);
%}

%code requires {
#ifndef YY_TYPEDEF_YY_SCANNER_T
#define YY_TYPEDEF_YY_SCANNER_T
typedef void* yyscan_t;
#endif
}

%output  "./exp_parser.c"
%defines "./exp_parser.h"
 
%define api.pure
%lex-param   { yyscan_t scanner }
%parse-param { int *ret }
%parse-param { yyscan_t scanner }


%union {
    int ival;
    char *sval;
}

%type <ival> expr

%token  <ival> INTEGER
%token  <sval> IDENTIFIER
%token  ISINC
%token  LPAREN RPAREN

%left   OP_ADD OP_SUB
%left   OP_MUL OP_DIV

%nonassoc COP_EQ COP_GE COP_LE COP_GT COP_LT

%%
program:
    statement;
statement:
     expr    {*ret = $1; /* printf("%d\n", $1); */ }
     ;
expr:
    INTEGER {$$ = $1;}
    | IDENTIFIER {
        $$ = DataMemory::get_val_auto($1); // Fetch value for the identifier
        free($1); // Free the memory allocated by strdup in lexer
    }
    | expr COP_EQ expr      {$$ = $1 = $3;}
    | expr COP_GE expr      {$$ = $1 >= $3;}
    | expr COP_LE expr      {$$ = $1 <= $3;}
    | expr COP_GT expr      {$$ = $1 > $3;}
    | expr COP_LT expr      {$$ = $1 < $3;}
    | expr OP_ADD expr      {$$ = $1 + $3;}
    | expr OP_SUB expr      {$$ = $1 - $3;}
    | expr OP_MUL expr      {$$ = $1 * $3;}
    | expr OP_DIV expr      {$$ = $1 / $3;}
    | LPAREN expr RPAREN    {$$ = $2;}
    ;
%%

void yyerror(int *ret, yyscan_t scanner, const char *msg) {
	fprintf (stderr, "\033[31mERROR\033[0m: %s\n", msg);
    exit(1);
}